package dcutils;

// Import Java JDK Classes
import java.util.AbstractCollection;

/**
 * Collects and reports any method argument violations.<br/>
 * @author dca
 */
public class Preconditions {
   /** A buffer containing messages of any violations which were recorded.<br/> */
   private StringBuffer violations;

   /** A delimiter string specifying how messages should be delineated.<br/> */
   private String delim;

   /**
    * Creates a new instance with the platform-specific newline string as the message delimiter.<br/>
    */
   public Preconditions() {
      this(String.format("%n"));
   } // END constructor

   /**
    * Creates a new instance with <code>delimiter</code> as the message delimiter.<br/>
    * @param delimiter The message <code>delimiter</code>.<br/>
    */
   public Preconditions(String delimiter) {
      violations = new StringBuffer();
      setDelimiter(delimiter);
   } // END constructor

   /**
    * Sets the message <code>delimiter</code>.<br/>
    * @param delimiter The message <code>delimiter</code>.<br/>
    */
   public void setDelimiter(String delimiter) {
      delim = delimiter;
   } // END setDelimiter

   /**
    * Resets the <code>violations</code> message buffer.<br/>
    */
   public void clearViolations() {
      violations = new StringBuffer();
   } // END clearViolations

   /**
    * Adds a violation <code>message</code> to the <code>violations</code> message buffer.<br/>
    * @param message The violation <code>message</code>.<br/>
    */
   private void addViolation(String message) {
      if(violated()) violations.append(delim);
      violations.append(message);
   } // END addViolation

   /**
    * Checks the <code>expression</code>, and optionally adds the <code>message</code> to the <code>violations</code> message buffer.<br/>
    * @param expression If false, the <code>message</code> will be added to the <code>violations</code> buffer; otherwise, nothing happens.<br/>
    * @param message The message to add to the <code>violations</code> buffer.<br/>
    * @return this A reference to this Preconditions object.<br/>
    */
   public Preconditions checkArgument(boolean expression, String message) {
      if(!expression) addViolation(message);
      return this;
   } // END checkArgument

   /**
    * Checks the <code>obj</code>, and, if it is null, adds the <code>message</code> to the <code>violations</code> message buffer.<br/>
    * @param obj The object to check for null.<br/>
    * @param message The message to add to the <code>violations</code> buffer.<br/>
    * @return this A reference to this Preconditions object.<br/>
    */
   public Preconditions checkNull(Object obj, String message) {
      if(null == obj) addViolation(message);
      return this;
   } // END checkNull

   /**
    * Checks the <code>str</code>, and if it is either null or empty, adds the <code>message</code> to the <code>violations</code> message buffer.<br/>
    * @param str The string to check for null or empty.<br/>
    * @param message The message to add to the <code>violations</code> buffer.<br/>
    * @return this A reference to this Preconditions object.<br/>
    */
   public Preconditions checkNullOrEmpty(String str, String message) {
      if(null == str) addViolation(message);
      else if(str.isEmpty()) addViolation(message);
      return this;
   } // END checkNullOrEmpty

   /**
    * Checks the <code>list</code>, and if it is either null or empty, adds the <code>message</code> to the <code>violations</code> message buffer.<br/>
    * @param list The list to check for null or empty.<br/>
    * @param message The message to add to the <code>violations</code> buffer.<br/>
    * @return this A reference to this Preconditions object.<br/>
    */
   public Preconditions checkNullOrEmpty(AbstractCollection<?> list, String message) {
      if(null == list) addViolation(message);
      else if(list.isEmpty()) addViolation(message);
      return this;
   } // END checkNullOrEmpty

   /**
    * Checks the <code>array</code>, and if it is either null, or zero length, adds the <code>message</code> to the <code>violations</code> message buffer.<br/>
    * @param array The array to check for null or empty.<br/>
    * @param message The message to add to the <code>violations</code> buffer.<br/>
    * @return this A reference to this Preconditions object.<br/>
    */
   public Preconditions checkNullOrEmpty(Object[] array, String message) {
      if(null == array) addViolation(message);
      else if(0 == array.length) addViolation(message);
      return this;
   } // END checkNullOrEmpty

   /**
    * Returns the string of delimited string messages in the <code>violations</code> message buffer.<br/>
    * @return <code>violations.toString()</code>
    */
   public String getViolationMessages() {
      return violations.toString();
   } // END getViolationMessages

   /**
    * Returns whether or not the <code>violations</code> message buffer is empty.<br/>
    * @return True if <code>violations</code> message buffer is NOT empty; false otherwise.<br/>
    */
   public boolean violated() {
      return !getViolationMessages().isEmpty();
   } // END violated

   /**
    * Checks if the <code>violations</code> message buffer is empty or not and throws an IllegalArgumentException if the buffer is NOT empty.<br/>
    * The IllegalArgumentException will contain the string of delimited messages contained in the <code>violations</code> message buffer.<br/>
    */
   public void reportViolations() {
      if(violated()) {
         throw new IllegalArgumentException(getViolationMessages());
      } // END if
   } // END reportViolations
} // END class Preconditions
